use crate::config::{Console, FileAppender};
use crate::{level_from_str, rotation_from_str};
use std::io;
use tracing::Subscriber;
use tracing_appender::non_blocking;
use tracing_appender::rolling::RollingFileAppender;
use tracing_subscriber::fmt::time::ChronoLocal;
use tracing_subscriber::{filter, fmt, registry, Layer};

/// 获取文件日志输出的[Layer]
pub fn get_file_layer<S>(
    appender: &FileAppender
) -> impl Layer<S>
where
    S: Subscriber + for<'span> registry::LookupSpan<'span> + 'static,
{
    let timer = ChronoLocal::new(appender.format.clone());
    let level_filter = level_from_str(&appender.level);
    let rotation = rotation_from_str(&appender.rotation);
    // 输出到文件中
    let file_appender = RollingFileAppender::builder()
        .max_log_files(appender.max_files)
        .rotation(rotation)
        .filename_prefix(&appender.prefix)
        .filename_suffix(&appender.suffix)
        .build(&appender.directory)
        .expect("日志初始化失败");
    
    // 创建非阻塞文件追加
    let (file_appender, guard) = non_blocking(file_appender);
    let guard = Box::new(guard);
    Box::leak(guard);
    
    let target = appender.target.clone();
    fmt::layer()
        .with_ansi(false)
        .with_timer(timer)
        .with_thread_names(appender.thread)
        .with_writer(file_appender)
        .with_line_number(appender.line_number)
        .with_filter(level_filter)
        .with_filter(filter::filter_fn(move |metadata| {
            target.is_empty() || metadata.target() == target
        }))
}

/// 获取控制台日志输出的[Layer]
pub fn get_console_layer<S>(
    console: &Console
) -> impl Layer<S>
where
    S: Subscriber + for<'span> registry::LookupSpan<'span> + 'static,
{
    let timer = ChronoLocal::new(console.format.clone());
    let level_filter = level_from_str(&console.level);
    
    // 创建非阻塞控制台打印
    let (stderr, guard) = non_blocking(io::stderr());
    let guard = Box::new(guard);
    Box::leak(guard);
    
    fmt::layer()
        .with_ansi(false)
        // 自定义数据时间格式
        .with_timer(timer)
        // 线程名
        .with_thread_names(console.thread)
        // 行数
        .with_line_number(console.line_number)
        // 输出到标准的成错误输出
        .with_writer(stderr)
        // 只记录level_filter级别及以上级别的日志
        .with_filter(level_filter)
}
